package com.alibaba.service.impl;

import com.alibaba.mapper.ProductMapper;
import com.alibaba.model.entity.Product;
import com.alibaba.service.ProductService;
import com.alibaba.utils.BizException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

import static com.alibaba.constants.OngoingProductSyncConstants.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.alibaba.constants.OngoingProductSyncConstants.ONGOING_PRODUCT_SYNC_LOCK;
import static com.alibaba.constants.OngoingProductSyncConstants.REDIS_KEY_PREFIX;

/**
 * 产品服务实现类，实现ProductService接口。
 */
@Slf4j
@Service
public class ProductServiceImpl implements ProductService {

    @Resource
    private ProductMapper productMapper;

    @Resource
    private RedisTemplate<String, Objects> redisTemplate;

    @Resource
    private RedissonClient redissonClient;

    @Override
    public List<Product> listAllProducts() {
        return productMapper.selectList(null);
    }

    @Override
    public List<Product> listHotProducts(int topN) {
        QueryWrapper<Product> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("view_count").last("LIMIT " + topN);
        return productMapper.selectList(wrapper);
    }

    @Override
    public Product getProductById(Long productId) {
        return productMapper.selectById(productId);
    }

    @Override
    public boolean addProduct(Product product) {
        int rows = productMapper.insert(product);
        if (rows <= 0) {
            throw new BizException("新增产品失败，product：" + product.toString());
        }
        return true;
    }

    @Override
    public boolean updateProduct(Product product) {
        // 获取全局分布式锁对象，保证同一时间只有一个线程可以更新Redis和数据库
        RLock lock = redissonClient.getLock(ONGOING_PRODUCT_SYNC_LOCK);
        boolean isLocked = false;

        try {
            // 尝试获取锁：
            // waitTime = 2分钟：如果锁被占用，最多等待1分钟获取锁
            // leaseTime = 2分钟：锁自动释放时间，防止线程异常导致锁永远不释放
            isLocked = lock.tryLock(2, 2, java.util.concurrent.TimeUnit.MINUTES);

            // 如果获取锁失败，则直接抛出业务异常，告知调用方更新被拒绝
            if (!isLocked) {
                throw new BizException("获取全局锁失败，更新产品被拒绝");
            }

            // 1️⃣ 更新数据库中的商品信息
            int rows = productMapper.updateById(product);
            // 如果更新失败（受影响行数 <= 0），抛出业务异常
            if (rows <= 0) {
                throw new BizException("更新产品失败，product：" + product.toString());
            }

            // 2️⃣ 检查商品状态是否下架（status == 0）
            if (product.getStatus() != null && product.getStatus() == 0) {
                // 拼接Redis Key，保持与定时任务写入一致
                String redisKey = REDIS_KEY_PREFIX + product.getId();
                // 直接删除Redis中缓存，保证下架商品不再被访问
                redisTemplate.delete(redisKey);
                // 打印日志，记录下架操作
                log.info("产品已下架，删除Redis中缓存，key: {}", redisKey);
                // 下架逻辑完成后直接返回
                return true;
            }

            // 3️⃣ 如果商品未下架，则更新Redis缓存
            // 拼接Redis Key，每个商品对应一个Hash Key
            String redisKey = REDIS_KEY_PREFIX + product.getId();

            // 构造Hash结构的数据
            Map<String, String> hash = getStringStringMap(product);

            // 4️⃣ 写入Redis Hash
            // opsForHash.putAll 将整个Map写入Redis Hash
            redisTemplate.opsForHash().putAll(redisKey, hash);
            // 设置过期时间，防止缓存长期占用Redis内存
            redisTemplate.expire(redisKey, 10, java.util.concurrent.TimeUnit.MINUTES);

            // 打印日志，记录Redis更新操作
            log.info("已更新Redis中产品数据，key: {}", redisKey);
            return true;

        } catch (InterruptedException e) {
            // 捕获线程中断异常，并重置线程中断标识
            Thread.currentThread().interrupt();
            throw new BizException("更新产品时线程中断");
        } finally {
            // 释放锁，确保不会出现死锁
            if (isLocked) {
                lock.unlock();
            }
        }
    }

    private static Map<String, String> getStringStringMap(Product product) {
        Map<String, String> hash = new HashMap<>();
        hash.put("name", product.getName());                      // 商品名称
        hash.put("price", product.getPrice().toString());         // 商品价格
        hash.put("stock", String.valueOf(product.getStock()));    // 库存
        hash.put("viewCount", String.valueOf(product.getViewCount())); // 浏览量
        hash.put("status", String.valueOf(product.getStatus()));  // 上下架状态
        return hash;
    }


    @Override
    public boolean deleteProduct(Long productId) {
        // 删除前可以考虑先删除缓存
        int rows = productMapper.deleteById(productId);
        if (rows <= 0) {
            throw new BizException("删除产品失败，productId：" + productId);
        }
        return true;
    }
}
